package com.woniu.util.handler;

import com.woniu.util.service.SecurityService;
import com.woniu.util.utils.JWTUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 校验jwt
 * 1.判断请求头是否携带jwt
 *      否:放行不处理
 *      是:代码往下走
 * 2.对前端传过来的jwt进行解密
 *       否:放行不处理
 *       是:走到第3步
 * 3.获取redis的jwt
 *         否:放行不处理
 *         是:走到第4步
 * 4.对比jwt
 *      否:放行不处理
 *      是:走到第5步
 * 5.给jwt续期
 *
 */
@Component
public class JWTFilter extends OncePerRequestFilter {
    @Autowired(required = false)
    private StringRedisTemplate stringRedisTemplate;

    @Autowired(required = false)
    private SecurityService securityService;
    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    FilterChain filterChain) throws ServletException, IOException {
        /**
         * 1.判断请求头是否携带jwt
         *       否:放行不处理
         *       是:代码往下走
         */
        String jwt = httpServletRequest.getHeader("jwt");
        if(jwt == null){
            //交给下一个过滤器处理
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        /**
         * 2.对前端传过来的jwt进行解密
         *      否:放行不处理
         *      是:走到第3步
         */
        if(!JWTUtil.decode(jwt)){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        /**
         * 3.获取redis的jwt
         *     否:放行不处理
         *     是:走到第4步
         */
        String username= (String) JWTUtil.getPayload(jwt).get("username");
        String redisJWT = stringRedisTemplate.opsForValue().get("jwt:" + username);
        if(redisJWT ==null){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        /**
         *  4.对比jwt
         *     否:放行不处理
         *     是:走到第5步
         */
        if(!redisJWT.equals(jwt)){
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }
        /**
         * 5.给jwt续期
         */
        stringRedisTemplate.opsForValue().set("jwt:"+username,jwt,30, TimeUnit.MINUTES);

        //把jwt放到security 容器中
        UserDetails userDetails = securityService.loadUserByUsername(username);

        UsernamePasswordAuthenticationToken upa = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),
                                                                                          userDetails.getPassword(),
                                                                                          userDetails.getAuthorities());

        SecurityContextHolder.getContext().setAuthentication(upa);
        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }
}
